#include "dynamicdatacachemanager.h"
#include <QtXml/QDomNode>
#include <QtXml/QDomElement>
#include <QtXml/QDomDocument>
#include <QtXml/QDomNodeList>
#include <QtXml/QDomText>
#include "unitconversionmanager.h"
#include "datamanager.h"
#include "layersmanager.h"
#include "singlelayeractor.h"
#include "effectcontainermanager.h"
#include "freesurroundboxactor.h"

namespace VrDataCore
{
	DynamicDataCacheManager::DynamicDataCacheManager():_surroundMin(-999999,-999999,0),_surroundMax(999999,999999,0)
	{}

	DynamicDataCacheManager::~DynamicDataCacheManager()
	{}

	void DynamicDataCacheManager::updatePosition(const QString& xmlstring)
	{
		QDomDocument domTree;
		QDomElement  root;
		bool boolsetvalue = false;
		if(domTree.setContent(xmlstring))   
		{
			root = domTree.documentElement();   
			QDomNodeList  nodelist=root.childNodes();  
			for(int i=0;i<nodelist.length();i++)   
			{   
				if(nodelist.item(i).nodeName()=="device")
				{
					DynamicObjectData everyobject;
					QDomNode mchildnode = nodelist.item(i);
					for(int k=0;k< mchildnode.childNodes().length();k++)
					{
						if(mchildnode.childNodes().item(k).nodeName()=="id")
						{
							everyobject._id = mchildnode.childNodes().item(k).toElement().text();
						}
						else if(mchildnode.childNodes().item(k).nodeName()=="property")
						{
							QDomNode childchild = mchildnode.childNodes().item(k);
							for(int m=0;m<childchild.childNodes().length();m++)
							{
								if(childchild.childNodes().item(m).nodeName()=="endposition")
								{
									everyobject._endPosition = childchild.childNodes().item(m).toElement().text();
								}
								else if(childchild.childNodes().item(m).nodeName()=="objecttype")
								{
									everyobject._objectType = childchild.childNodes().item(m).toElement().text();
								}
							}
						}
					}
					osg::Vec2 pos;
					QStringList endlist = everyobject._endPosition.split(',',QString::SkipEmptyParts);
					if(everyobject._id !="" && endlist.size() == 2)
					{
						pos.x() = endlist.at(0).toFloat();
						pos.y() = endlist.at(1).toFloat();
						float x,y;
						UnitConversionManager::GetInstance().getAfterConverPointRTS(x,y,pos.x(),pos.y());
						osg::Vec3 scenepos(x,y,_environmentPos.z());

						QMap<QString,DynamicObjectData>::Iterator objitem = _dynamicObjectsPosMap.find(everyobject._id);
						if(objitem!=_dynamicObjectsPosMap.end())
						{
							update(objitem.value(),scenepos);
						}
						else
						{
							create(everyobject,scenepos);
						}
					}
				}
			}
		}
	}

	void DynamicDataCacheManager::clearAll()
	{
		_dynamicObjectsPosMap.clear();
		_objectsPropertyMap.clear();
	}

	void DynamicDataCacheManager::mapChanged()
	{
		LayersManager::OceanSetting setting;
		LayersManager::GetInstance().getOceanEnable(setting);
		QVector<CoreBase::ActorBase*> surrounds = LayersManager::GetInstance().getAllObjects(CLASS_LAYER,CLASS_FREESURROUNDBOX,false);
		if(surrounds.size() == 1)
		{
			FreeSurroundBoxActor* surround = dynamic_cast<FreeSurroundBoxActor*>(surrounds.at(0));
			surround->getVertex(_surroundMin,_surroundMax);
		}
		LayersManager::OceanSetting oceansetting;
		LayersManager::GetInstance().getOceanEnable(oceansetting);
		_environmentPos = oceansetting._pos;
	}

	void DynamicDataCacheManager::create(DynamicObjectData& data,osg::Vec3 pos)
	{
		if(pos.x() > _surroundMin.x() && pos.x() < _surroundMax.x() 
				&& pos.y() > _surroundMin.y() && pos.y() < _surroundMax.y())
		{
			CoreBase::ActorBase* obj = DataManager::GetInstance().getResourceActorByType(data._objectType);
			if(obj!=NULL)
			{
				osg::ref_ptr<CoreBase::ActorBase> newdevice = obj->clone();
				newdevice->copyPropertiesFrom(*obj);
				newdevice->setBindingId(data._id);
				dynamic_cast<DeviceActor*>(newdevice.get())->setToStaticActor(false);
				dynamic_cast<SingleLayerActor*>(LayersManager::GetInstance().getDynamicLayer())->addChild(newdevice);
				data._deviceActor = dynamic_cast<DeviceActor*>(newdevice.get());
				osg::ref_ptr<UniformMotion> effect = new UniformMotion;
				effect->setMotionTotalTime(5000);
				data._deviceActor->setTranslation(pos);
				effect->setStartPosition(pos);
				effect->setEndPosition(pos+osg::Vec3(0.1,0,0));
				data._motionEffect = effect;
				effect->apply(newdevice.get());
				osg::ref_ptr<FadeEffect> fadeeffect = new FadeEffect;
				data._fadeEffect = fadeeffect;
				data._fadeEffect->apply(newdevice.get());
				data._removeRequest = false;
				_dynamicObjectsPosMap.insert(data._id,data);
				callObjectCreateFun(newdevice);
			}
		}
	}

	void DynamicDataCacheManager::update(DynamicObjectData& data,osg::Vec3 pos)
	{
		data._motionEffect->setStartPosition(data._deviceActor->getTranslation());
		data._motionEffect->setEndPosition(pos);
		data._motionEffect->apply(data._deviceActor.get());
		if(!data._fadeEffect->isUpdating())
		{
			data._fadeEffect->unApply(data._deviceActor.get());
		}
		if(pos.x() < _surroundMin.x() || pos.x() > _surroundMax.x() 
				|| pos.y() < _surroundMin.y() || pos.y() > _surroundMax.y())
		{
			if(!data._fadeEffect->isUpdating() && data._removeRequest)
			{
				remove(data);
			}
			else
			{
				data._removeRequest = true;
				data._fadeEffect->fadeIn(false);
				data._fadeEffect->apply(data._deviceActor);
				data._motionEffect->unApply(data._deviceActor);
			}
		}
	}

	void DynamicDataCacheManager::remove(DynamicObjectData data)
	{
		QMap<QString,DynamicObjectData>::Iterator objitem = _dynamicObjectsPosMap.find(data._id);
		if(objitem!=_dynamicObjectsPosMap.end())
		{
			callObjectDeleteFun(objitem.value()._deviceActor);
			dynamic_cast<SingleLayerActor*>(LayersManager::GetInstance().getDynamicLayer())->removeChild(objitem.value()._deviceActor);
			_dynamicObjectsPosMap.remove(data._id);
		}
	}

	void DynamicDataCacheManager::setStaticDynamicData(const QString& xmlstring)
	{
		QDomDocument domTree;
		QDomElement  root;
		if(domTree.setContent(xmlstring))   
		{
			root = domTree.documentElement();   
			QDomNodeList  nodelist=root.childNodes();
			QString id = "";
			for(int i=0;i<nodelist.length();i++)   
			{   
				if(nodelist.item(i).nodeName()=="device")
				{
					QDomNode mchildnode = nodelist.item(i);
					QMap<QString,QString> propertymap;
					for(int k=0;k< mchildnode.childNodes().length();k++)
					{
						if(mchildnode.childNodes().item(k).nodeName()=="id")
						{
							id = mchildnode.childNodes().item(k).toElement().text();
						}
						else if(mchildnode.childNodes().item(k).nodeName()=="properties")
						{
							QDomNode childchild = mchildnode.childNodes().item(k);
							for(int m=0;m<childchild.childNodes().length();m++)
							{
								if(childchild.childNodes().item(m).nodeName()=="property")
								{
									QDomNode everyproperty = childchild.childNodes().item(m);
									QString propertyname = "";
									QString propertyvalue = "";
									for(int j=0;j<everyproperty.childNodes().length();++j)
									{
										if(everyproperty.childNodes().item(j).nodeName()=="name")
											propertyname =  everyproperty.childNodes().item(j).toElement().text();
										else if(everyproperty.childNodes().item(j).nodeName()=="value")
											propertyvalue = everyproperty.childNodes().item(j).toElement().text();
									}
									if(propertyname!="" && propertyvalue!="")
										propertymap.insert(propertyname,propertyvalue);
								}
							}
						}
					}
					if(id!="" && propertymap.size()>0)
					{
						if(!_objectsPropertyMap.contains(id))
						{
							CoreBase::ActorBase* dev = LayersManager::GetInstance().getActorById(id,CLASS_LAYER,CLASS_DEVICE,true);
							if(dev!=NULL)
							{
								DynamicObjectData newstruct;
								newstruct._id = id;
								newstruct._deviceActor = dynamic_cast<DeviceActor*>(dev);
								CoreBase::ActorBase* resourceactor = DataManager::GetInstance().getResourceActorByName(dev->getName()).get();
								newstruct._resourceActor = dynamic_cast<DeviceActor*>(resourceactor);
								newstruct._professionProperty = dynamic_cast<ProfessionPropertyDefine*>(
												newstruct._resourceActor->getProfessionPropertyDefine()->clone().get());
								_objectsPropertyMap.insert(id,newstruct);
							}
						}
						if(_objectsPropertyMap.contains(id))
						{
							ProfessionPropertyDefine* devproperty = _objectsPropertyMap.value(id)._professionProperty.get();
							QMap<QString,QString>::Iterator iter = propertymap.begin();
							for(;iter!=propertymap.end();++iter)
							{
								devproperty->setPropertyValue(iter.key(),iter.value());
							}
						}
					}
				}
			}
		}
	}

	void DynamicDataCacheManager::showDeviceDataWidget(const QString& id)
	{
		bool isupdate = _currentPropertyWidgetId == id;
		VrDataCore::EffectContainerManager::GetInstance().showProfessionProperty(_objectsPropertyMap.value(id
			)._professionProperty->getAllPropertyData(),isupdate);
		_currentPropertyWidgetId = id;
	}

	void DynamicDataCacheManager::hideDeviceDataWidget()
	{
		VrDataCore::EffectContainerManager::GetInstance().hideProfessionPropertyWidget();
		_currentPropertyWidgetId = "";
	}

	void DynamicDataCacheManager::callObjectCreateFun(osg::ref_ptr<CoreBase::ActorBase> p)
	{
		if(_createFuncMap.size()>0)
		{
			PramBase* pram = new Parm1<osg::ref_ptr<CoreBase::ActorBase>>(p);
			QMap<QString,osg::ref_ptr<FuncBase>>::Iterator iter = _createFuncMap.begin();
			for(;iter!=_createFuncMap.end();++iter)
			{
				iter.value()->callFunc(pram);
			}
		}
	}

	void DynamicDataCacheManager::callObjectDeleteFun(osg::ref_ptr<CoreBase::ActorBase> p)
	{
		if(_deleteFuncMap.size()>0)
		{
			PramBase* pram = new Parm1<osg::ref_ptr<CoreBase::ActorBase>>(p);
			QMap<QString,osg::ref_ptr<FuncBase>>::Iterator iter = _deleteFuncMap.begin();
			for(;iter!=_deleteFuncMap.end();++iter)
			{
				iter.value()->callFunc(pram);
			}
		}
	}
}
//position xml
//<devices>
//<device>
//<id>90909090</id>
//<property>
//<endposition></endposition>
//<objecttype></objecttype>
//</property>
//</device>
//</devices>

//static/dynamic data xml
//<devices>
//<device>
//<id>90909090</id>
//<properties>
//<property>
//<name></name>
//<value></value>
//<property>
//<property>
//<name></name>
//<value></value>
//<property>
//</properties>
//</device>
//</devices>